/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_orm.htm
 *
 * Zhiqim ORM is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.orm.dbo;

import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

import org.zhiqim.kernel.annotation.AnNullable;
import org.zhiqim.kernel.model.maps.LinkedMapSS;
import org.zhiqim.kernel.model.maps.MapSO;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Types;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.orm.ORMConstants;
import org.zhiqim.orm.ORMException;
import org.zhiqim.orm.dbo.condition._Equal;
import org.zhiqim.orm.dbo.condition._EqualNot;
import org.zhiqim.orm.dbo.condition._Expression;
import org.zhiqim.orm.dbo.condition._Function;
import org.zhiqim.orm.dbo.condition._In;
import org.zhiqim.orm.dbo.condition._InNot;
import org.zhiqim.orm.dbo.condition._IsEmpty;
import org.zhiqim.orm.dbo.condition._IsNotEmpty;
import org.zhiqim.orm.dbo.condition._IsNotNull;
import org.zhiqim.orm.dbo.condition._IsNull;
import org.zhiqim.orm.dbo.condition._Like;
import org.zhiqim.orm.dbo.condition._LikeL;
import org.zhiqim.orm.dbo.condition._LikeNot;
import org.zhiqim.orm.dbo.condition._LikeNotL;
import org.zhiqim.orm.dbo.condition._LikeNotR;
import org.zhiqim.orm.dbo.condition._LikeR;
import org.zhiqim.orm.dbo.condition._Or;
import org.zhiqim.orm.dbo.condition._ThenG;
import org.zhiqim.orm.dbo.condition._ThenGE;
import org.zhiqim.orm.dbo.condition._ThenL;
import org.zhiqim.orm.dbo.condition._ThenLE;

/**
 * 条件管理器，管理条件和可替换表
 * 1. @see Selector     查询器
 * 2. @see Updater      更新器
 *
 * @version v1.0.0 @author zouzhigang 2016-6-27 新建与整理
 */
abstract class Conditioner<C extends Conditioner<?>> implements Serializable, ORMConstants
{
    private static final long serialVersionUID = 1L;
    
    protected List<Condition> conditionList = null;
    protected LinkedMapSS replaceMap = null;
    
    @AnNullable /** 返回对应的适配信息 */
    public LinkedMapSS getReplaceMap()
    {
        return replaceMap;
    }
    
    @AnNullable /** 返回对应的适配信息 */
    public List<Condition> getConditionList()
    {
        return conditionList;
    }
    
    /** 是否有可远的表 */
    public boolean hasReplace()
    {
        return replaceMap != null && !replaceMap.isEmpty();
    }
    
    /** 是否有条件 */
    public boolean hasCondition()
    {
        return conditionList != null && !conditionList.isEmpty();
    }
    
    /******************************************************/
    //条件列表管理
    /******************************************************/
    
    /** 增加[可能][相等]条件 */
    public C addMaybe(String field, Object value)
    {
        if (!chkMaybeFieldValue(field, value))
            return self();
        
        addCondition(new _Equal(field, value));
        return self();
    }
    
    /** 增加[强制][相等]条件 */
    public C addMust(String field, Object value)
    {
        chkMustFieldValue(field, value);
        addCondition(new _Equal(field, value));
        return self();
    }

    /** 增加[可能][不等]条件 */
    public C addMaybeNotEqual(String field, Object value)
    {
        if (!chkMaybeFieldValue(field, value))
            return self();
        
        addCondition(new _EqualNot(field, value));
        return self();
    }
    
    /** 增加[强制][不等]条件 */
    public C addMustNotEqual(String field, Object value)
    {
        chkMustFieldValue(field, value);
        addCondition(new _EqualNot(field, value));
        return self();
    }
    
    /** 增加[可能][LIKE]条件 */
    public C addMaybeLike(String field, Object value)
    {
        if (!chkMaybeFieldValue(field, value))
            return self();
        
        addCondition(new _Like(field, String.valueOf(value)));
        return self();
    }
    
    /** 增加[强制][LIKE]条件 */
    public C addMustLike(String field, Object value)
    {
        chkMustFieldValue(field, value);
        addCondition(new _Like(field, String.valueOf(value)));
        return self();
    }
    
    /** 增加[可能][LIKE_LEFT]查询条件 */
    public C addMaybeLikeLeft(String field, Object value)
    {
        if (!chkMaybeFieldValue(field, value))
            return self();
        
        addCondition(new _LikeL(field, String.valueOf(value)));
        return self();
    }
    
    /** 增加[强制][LIKE_LEFT]条件 */
    public C addMustLikeLeft(String field, Object value)
    {
        chkMustFieldValue(field, value);
        addCondition(new _LikeL(field, String.valueOf(value)));
        return self();
    }
    
    /** 增加[可能][LIKE_RIGHT]查询条件 */
    public C addMaybeLikeRight(String field, Object value)
    {
        if (!chkMaybeFieldValue(field, value))
            return self();
        
        addCondition(new _LikeR(field, String.valueOf(value)));
        return self();
    }
    
    /** 增加[强制][LIKE_RIGHT]查询条件 */
    public C addMustLikeRight(String field, Object value)
    {
        chkMustFieldValue(field, value);
        addCondition(new _LikeR(field, String.valueOf(value)));
        return self();
    }
    
    /** 增加[可能][NOT LIKE]条件 */
    public C addMaybeNotLike(String field, Object value)
    {
        if (!chkMaybeFieldValue(field, value))
            return self();
        
        addCondition(new _LikeNot(field, String.valueOf(value)));
        return self();
    }
    
    /** 增加[强制][NOT LIKE]条件 */
    public C addMustNotLike(String field, Object value)
    {
        chkMustFieldValue(field, value);
        addCondition(new _LikeNot(field, String.valueOf(value)));
        return self();
    }
    
    /** 增加[可能][NOT LIKE_LEFT]查询条件 */
    public C addMaybeNotLikeLeft(String field, Object value)
    {
        if (!chkMaybeFieldValue(field, value))
            return self();
        
        addCondition(new _LikeNotL(field, String.valueOf(value)));
        return self();
    }
    
    /** 增加[强制][NOT LIKE_LEFT]条件 */
    public C addMustNotLikeLeft(String field, Object value)
    {
        chkMustFieldValue(field, value);
        addCondition(new _LikeNotL(field, String.valueOf(value)));
        return self();
    }
    
    /** 增加[可能][NOT LIKE_RIGHT]查询条件 */
    public C addMaybeNotLikeRight(String field, Object value)
    {
        if (!chkMaybeFieldValue(field, value))
            return self();
        
        addCondition(new _LikeNotR(field, String.valueOf(value)));
        return self();
    }
    
    /** 增加[强制][NOT LIKE_RIGHT]查询条件 */
    public C addMustNotLikeRight(String field, Object value)
    {
        chkMustFieldValue(field, value);
        addCondition(new _LikeNotR(field, String.valueOf(value)));
        return self();
    }
    
    /** 增加[可能][大于]查询条件 */
    public C addMaybeThenG(String field, Object value)
    {
        if (!chkMaybeFieldValue(field, value))
            return self();
        
        addCondition(new _ThenG(field, value));
        return self();
    }
    
    /** 增加[强制][大于]查询条件 */
    public C addMustThenG(String field, Object value)
    {
        chkMustFieldValue(field, value);
        addCondition(new _ThenG(field, value));
        return self();
    }
    
    /** 增加[可能][大于等于]查询条件 */
    public C addMaybeThenGE(String field, Object value)
    {
        if (!chkMaybeFieldValue(field, value))
            return self();
        
        addCondition(new _ThenGE(field, value));
        return self();
    }
    
    /** 增加[强制][大于等于]查询条件 */
    public C addMustThenGE(String field, Object value)
    {
        chkMustFieldValue(field, value);
        addCondition(new _ThenGE(field, value));
        return self();
    }
    
    /** 增加[可能][小于]查询条件 */
    public C addMaybeThenL(String field, Object value)
    {
        if (!chkMaybeFieldValue(field, value))
            return self();
        
        addCondition(new _ThenL(field, value));
        return self();
    }
    
    /** 增加[强制][小于]查询条件 */
    public C addMustThenL(String field, Object value)
    {
        chkMustFieldValue(field, value);
        addCondition(new _ThenL(field, value));
        return self();
    }
    
    /** 增加[可能][小于等于]查询条件 */
    public C addMaybeThenLE(String field, Object value)
    {
        if (!chkMaybeFieldValue(field, value))
            return self();
        
        addCondition(new _ThenLE(field, value));
        return self();
    }
    
    /** 增加[强制][小于等于]查询条件 */
    public C addMustThenLE(String field, Object value)
    {
        chkMustFieldValue(field, value);
        addCondition(new _ThenLE(field, value));
        return self();
    }
    
    /** 增加[可能][is null]查询条件 */
    public C addMaybeIsNull(String field)
    {
        if (!chkMaybeFieldValue(field))
            return self();
        
        addCondition(new _IsNull(field));
        return self();
    }
    
    /** 增加[强制][is null]查询条件 */
    public C addMustIsNull(String field)
    {
        chkMustFieldValue(field);
        addCondition(new _IsNull(field));
        return self();
    }
    
    /** 增加[可能][is not null]查询条件 */
    public C addMaybeIsNotNull(String field)
    {
        if (!chkMaybeFieldValue(field))
            return self();
        
        addCondition(new _IsNotNull(field));
        return self();
    }
    
    /** 增加[强制][is not null]查询条件 */
    public C addMustIsNotNull(String field)
    {
        chkMustFieldValue(field);
        addCondition(new _IsNotNull(field));
        return self();
    }
    
    /** 增加[可能][is null or = '']查询条件 */
    public C addMaybeIsEmpty(String field)
    {
        if (!chkMaybeFieldValue(field))
            return self();
        
        addCondition(new _IsEmpty(field));
        return self();
    }
    
    /** 增加[强制][is null or = '']查询条件 */
    public C addMustIsEmpty(String field)
    {
        chkMustFieldValue(field);
        addCondition(new _IsEmpty(field));
        return self();
    }
    
    /** 增加[可能][is not null and <> '']查询条件 */
    public C addMaybeIsNotEmpty(String field)
    {
        if (!chkMaybeFieldValue(field))
            return self();
        
        addCondition(new _IsNotEmpty(field));
        return self();
    }
    
    /** 增加[强制][is not null and <> '']查询条件 */
    public C addMustIsNotEmpty(String field)
    {
        chkMustFieldValue(field);
        addCondition(new _IsNotEmpty(field));
        return self();
    }
    
    /** 增加[可能][in][String]查询条件 */
    public C addMaybeIn(String field, String ... values)
    {
        if (!chkMaybeFieldValue(field, values))
            return self();
        
        addCondition(new _In(field, values));
        return self();
    }
    
    /** 增加[强制][in][String]查询条件 */
    public C addMustIn(String field, String ... values)
    {
        chkMustFieldValue(field, values);
        addCondition(new _In(field, values));
        return self();
    }
    
    /** 增加[可能][in][int]查询条件 */
    public C addMaybeIn(String field, int ... values)
    {
        if (!chkMaybeFieldValue(field, values))
            return self();
        
        addCondition(new _In(field, values));
        return self();
    }
    
    /** 增加[强制][in][int]查询条件 */
    public C addMustIn(String field, int ... values)
    {
        chkMustFieldValue(field, values);
        addCondition(new _In(field, values));
        return self();
    }
    
    /** 增加[可能][in][long]查询条件 */
    public C addMaybeInLong(String field, long ... values)
    {
        if (!chkMaybeFieldValue(field, values))
            return self();
        
        addCondition(new _In(field, values));
        return self();
    }
    
    /** 增加[强制][in][long]查询条件 */
    public C addMustInLong(String field, long ... values)
    {
        chkMustFieldValue(field, values);
        addCondition(new _In(field, values));
        return self();
    }
    
    /** 增加[可能][not in][String]查询条件 */
    public C addMaybeNotIn(String field, String ... values)
    {
        if (!chkMaybeFieldValue(field, values))
            return self();
        
        addCondition(new _InNot(field, values));
        return self();
    }
    
    /** 增加[强制][not in][String]查询条件 */
    public C addMustNotIn(String field, String ... values)
    {
        chkMustFieldValue(field, values);
        addCondition(new _InNot(field, values));
        return self();
    }
    
    /** 增加[可能][not in][int]查询条件 */
    public C addMaybeNotIn(String field, int ... values)
    {
        if (!chkMaybeFieldValue(field, values))
            return self();
        
        addCondition(new _InNot(field, values));
        return self();
    }
    
    /** 增加[强制][not in][int]查询条件 */
    public C addMustNotIn(String field, int ... values)
    {
        chkMustFieldValue(field, values);
        addCondition(new _InNot(field, values));
        return self();
    }
    
    /** 增加[可能][not in][long]查询条件 */
    public C addMaybeNotInLong(String field, long ... values)
    {
        if (!chkMaybeFieldValue(field, values))
            return self();
        
        addCondition(new _InNot(field, values));
        return self();
    }
    
    /** 增加[强制][not in][long]查询条件 */
    public C addMustNotInLong(String field, long ... values)
    {
        chkMustFieldValue(field, values);
        addCondition(new _InNot(field, values));
        return self();
    }
    
    /*****************************************************************/
    //表达式管理开始
    /*****************************************************************/
    
    /** 增加相等表达式 */
    public C addExpression(String field, String expression)
    {
        return addExpression(field, expression, Condition.EQUAL);
    }
    
    /** 增加不等表达式 */
    public C addExpressionNotEqual(String field, String expression)
    {
        return addExpression(field, expression, Condition.EQUAL_NOT);
    }
    
    /** 增加大于表达式 */
    public C addExpressionThenG(String field, String expression)
    {
        return addExpression(field, expression, Condition.THEN_G);
    }
    
    /** 增加大于等于表达式 */
    public C addExpressionThenGE(String field, String expression)
    {
        return addExpression(field, expression, Condition.THEN_GE);
    }
    
    /** 增加小于表达式 */
    public C addExpressionThenL(String field, String expression)
    {
        return addExpression(field, expression, Condition.THEN_L);
    }
    
    /** 增加小于等于表达式 */
    public C addExpressionThenLE(String field, String expression)
    {
        return addExpression(field, expression, Condition.THEN_LE);
    }
    
    /** 增加表达式 */
    private C addExpression(String field, String expression, String condition)
    {
        Asserts.notEmptyBlank(field, _FIELD_);
        Asserts.notEmptyBlank(expression, _VALUE_);
        
        addCondition(new _Expression(field, expression, condition));
        return self();
    }
    
    /*****************************************************************/
    //函数管理开始
    /*****************************************************************/
    
    /** 增加相等函数 */
    public C addFunction(String function, String value)
    {
        return addFunction(function, value, Condition.EQUAL);
    }
    
    /** 增加不等函数 */
    public C addFunctionNotEqual(String function, String value)
    {
        return addFunction(function, value, Condition.EQUAL_NOT);
    }
    
    /** 增加大于函数 */
    public C addFunctionThenG(String function, String value)
    {
        return addFunction(function, value, Condition.THEN_G);
    }
    
    /** 增加大于等于函数 */
    public C addFunctionThenGE(String function, String value)
    {
        return addFunction(function, value, Condition.THEN_GE);
    }
    
    /** 增加小于函数 */
    public C addFunctionThenL(String function, String value)
    {
        return addFunction(function, value, Condition.THEN_L);
    }
    
    /** 增加小于等于函数 */
    public C addFunctionThenLE(String function, String value)
    {
        return addFunction(function, value, Condition.THEN_LE);
    }
    
    /** 增加函数 */
    private C addFunction(String function, String value, String condition)
    {
        Asserts.notEmptyBlank(function, "function");
        Asserts.notEmptyBlank(value, _VALUE_);
        
        addCondition(new _Function(function, value, condition));
        return self();
    }
    
    /*****************************************************************/
    //表达式管理结束
    /*****************************************************************/
    
    /**
     * 增加或者列表
     * 
     * @param selector  否则列表由多个条件组成
     * @return          本对象
     */
    public C addOr(Selector selector)
    {
        List<Condition> conditionList = selector.getConditionList();
        
        Asserts.as(conditionList != null?null:"增加[or]查询条件不能为空");
        Asserts.as(conditionList.size() >= 2?null:"增加[or]查询条件必须>=2个");
        
        _Or or = new _Or();
        for (Condition condition : conditionList)
        {
            or.addCondition(condition);
        }
        
        addCondition(or);
        return self();
    }
    
    /*****************************************************************/
    //条件列表管理结束
    /*****************************************************************/
    
    /**
     * 组装Where条件的SQL语句
     * 
     * @param dbo               _Dbo/_Table/_View三种的一种
     * @param paramMap          参数表
     * @return                  SQL字符串
     * @throws ORMException     异常
     */
    public String getWhereSQL(Dbo dbo, MapSO paramMap) throws ORMException
    {
        if (conditionList == null || conditionList.isEmpty())
            return _EMPTY_;
        
        StringBuilder whereSQL = new StringBuilder();
        //第一个
        whereSQL.append(" where ").append(conditionList.get(0).toSql(dbo, paramMap));
        //后面的
        for (int i=1;i<conditionList.size();i++)
        {
            whereSQL.append(" and ").append(conditionList.get(i).toSql(dbo, paramMap));
        }
        
        return whereSQL.toString();
    }
    
    /** 返回子类实例 */
    @SuppressWarnings("unchecked")
    protected final C self()
    {
        return (C)this;
    }
    
    /**
     * 增加适配信息
     * 
     * @param key 适配建
     * @param value 适配值
     */
    protected void addReplaceInner(String key, String value)
    {
        if (replaceMap == null)
            replaceMap = new LinkedMapSS(2);
        
        replaceMap.put(key, value);
    }
    
    /**
     * 增加查询条件
     * 
     * @param condition 条件
     */
    protected void addCondition(Condition condition)
    {
        if (conditionList == null)
            conditionList = new ArrayList<Condition>(3);
        
        conditionList.add(condition);
    }
    
    /**
     * 可能性检查字段是否为空，为空返回false，否则返回true
     * 
     * @param field     字段
     * @return          为空返回false，否则返回true
     */
    protected boolean chkMaybeFieldValue(String field)
    {
        return !Validates.isEmptyBlank(field);
    }
    
    /**
     * 强制性检查字段是否为空，为空返回false，否则返回true
     * 
     * @param field     字段
     */
    protected void chkMustFieldValue(String field)
    {
        Asserts.notEmptyBlank(field);
    }
    
    /**
     * 可能性检查字段和值是否为空，为空返回false，否则返回true
     * 
     * @param field     字段
     * @param value     值
     * @return          为空返回false，否则返回true
     */
    protected boolean chkMaybeFieldValue(String field, Object value)
    {
        if (Validates.isEmptyBlank(field) || value == null)
            return false;
        
        if (value instanceof String && Validates.isEmpty((String)value))
            return false;
        
        if (value instanceof Integer && ((Integer)value) == -1)
            return false;
        
        if (value instanceof Long && ((Long)value) == -1)
            return false;
        
        if (Types.isArray(value))
        {
            if (Array.getLength(value) == 0)
                return false;
        }
        
        return true;
    }
    
    /**
     * 强制性检查字段和值是否为空，为空抛非法参数异常
     * 
     * @param field     字段
     * @param value     值
     */
    protected void chkMustFieldValue(String field, Object value)
    {
        Asserts.notEmptyBlank(field, _FIELD_);
        Asserts.notNull(value,       _VALUE_);
        
        Asserts.as(!(value instanceof String && Validates.isEmpty((String)value)) ? null : "字段["+field+"]的["+value+"]为String型时值不能为空字符串");
        Asserts.as(!(value instanceof Integer && ((Integer)value) == -1)          ? null : "字段["+field+"]的["+value+"]为int型时值不能为-1");
        Asserts.as(!(value instanceof Long && ((Long)value) == -1)                ? null : "字段["+field+"]的["+value+"]为long型时值不能为-1");
        
        if (Types.isArray(value))
        {
            Asserts.as(Array.getLength(value) > 0 ? null : "字段["+field+"]或["+value+"]为Array型时数目必须>0");
        }
    }
}
